package se.webbzon.oschi01.sound;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;

import se.webbzon.boltzmann.debug.Debug;

public class URLWavSource implements ClipSource, DataLineSource {
	
	// The URL of the WavSource
	private final URL url;
	
	// The audio format
	private final AudioFormat af;
	
	// The size of the audio resource
	private final int size;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new WavSource by reading the audio format and data
	 * from the provided URL. **/
	private URLWavSource(URL url) throws IOException {
		this.url = url;
		try {
			AudioInputStream ais =  AudioSystem.getAudioInputStream(url);
			af = ais.getFormat();
			int read;
			int size = 0;
			byte[] frame = new byte[af.getFrameSize()];
			while ((read = ais.read(frame, 0, frame.length)) != -1) {
				size += read;
				size += ais.skip(Long.MAX_VALUE);
			}
			this.size = size;
		} catch (UnsupportedAudioFileException e) {
			throw new IOException(e);
		}
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Creates a new WavSource from an URL. **/
	public static final URLWavSource createSource(URL url) throws IOException {
		URLWavSource source = new URLWavSource(url);
		return source;
	}

	@Override public void setupClip(Clip clip) throws IOException, LineUnavailableException {
		try {
			clip.open(AudioSystem.getAudioInputStream(url));
		} catch (UnsupportedAudioFileException e) {
			Debug.report(e);
		}
	}

	@Override public FiniteSound createSound() throws SoundException {
		try {
			return new DataLineSound(this);
		} catch (IOException | LineUnavailableException e) {
			throw new SoundException(e);
		}
	}

	@Override public AudioFormat getFormat() {
		return af;
	}

	@Override public InputStream createInputStream() throws IOException {
		try {
			return AudioSystem.getAudioInputStream(url);
		} catch (UnsupportedAudioFileException e) {
			throw new IOException(e);
		}
	}

	@Override public int getSize() {
		return size;
	}

}
